package com.stellar.circle.domain.sPost.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.stellar.auth.api.dto.UserInfoDTO;
import com.stellar.circle.basic.entity.*;
import com.stellar.circle.basic.service.*;
import com.stellar.circle.constants.CircleConstants;
import com.stellar.circle.constants.ErrorCodeConstants;
import com.stellar.circle.controller.admin.sPost.vo.SPostRequestPageVO;
import com.stellar.circle.controller.admin.sPost.vo.SPostRequestVO;
import com.stellar.circle.controller.admin.sPost.vo.SPostResponseVO;
import com.stellar.circle.controller.miniApp.sPost.vo.PostPinRequestVO;
import com.stellar.circle.controller.miniApp.sPost.vo.TimeSlotPriceVO;
import com.stellar.circle.convert.SPostConvert;
import com.stellar.circle.domain.sPost.SPostDomainService;

import com.stellar.circle.enums.PostLikeTypeEnums;
import com.stellar.circle.redis.RedisCacheKey;
import com.stellar.circle.redis.post.PinOrderNoGenerator;
import com.stellar.circle.rpc.UserRPC;
import com.stellar.core.context.LoginContextHolder;
import com.stellar.redis.core.util.RedisUtil;
import com.stellar.web.core.bean.PageResult;
import com.stellar.web.core.constants.AuthUserConstants;
import com.stellar.web.core.enums.IsDeletedFlagEnum;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.stellar.circle.constants.CircleConstants.IS_PINNED;
import static com.stellar.core.util.ServiceExceptionUtil.exception;

/**
 * 校园墙帖子表领域服务实现
 *
 * @author Jqchan
 * @version 1.0
 * @date 2025-05-17 19:23:37
 */
@Service
public class SPostDomainServiceImpl implements SPostDomainService {

    @Resource
    private SPostService sPostService;

    @Resource
    private SPostTagService sPostTagService;

    @Resource
    private SPostTagMappingService sPostTagMappingService;

    @Resource
    private SPostLikeService sPostLikeService;

    @Resource
    private SPostCategoryService sPostCategoryService;

    @Resource
    private SSchoolService sSchoolService;

    @Resource
    private UserRPC userRPC;

    @Resource
    private PinOrderNoGenerator pinOrderNoGenerator;

    @Resource
    private RedisUtil redisUtil;


    @Override
    public PageResult<SPostResponseVO> page(SPostRequestPageVO requestPageVO) {
        PageResult<SPostResponseVO> pageResult = new PageResult<>();
        SPost queryEntity = SPostConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        // 非超级管理员身份只能查看已经发布的帖子【默认只显示已发布的帖子】
        if (!AuthUserConstants.SUPER_ADMIN.equals(LoginContextHolder.getRole())) {
            queryEntity.setPostStatus(CircleConstants.POST_STATUS_PUBLISHED);
        }

        List<SPost> entities = sPostService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = sPostService.count(queryEntity);
        List<SPostResponseVO> vos = SPostConvert.INSTANCE.convertEntityToRespList(entities);


        //  批量预加载数据
        List<Long> postIds = entities.stream().map(SPost::getId).collect(Collectors.toList());
        List<Long> userIds = entities.stream().map(SPost::getUserId).distinct().collect(Collectors.toList());
        List<Long> categoryIds = entities.stream().map(SPost::getCategoryId).distinct().collect(Collectors.toList());
        List<Long> schoolIds = entities.stream().map(SPost::getSchoolId).distinct().collect(Collectors.toList());

        // 批量查询用户信息
        Map<Long, UserInfoDTO> userMap = userRPC.batchQueryByIds(userIds).stream()
                .collect(Collectors.toMap(UserInfoDTO::getId, Function.identity()));

        // 批量查询分类信息
        Map<Long, String> categoryMap = sPostCategoryService.batchQueryCategoryNames(categoryIds);

        // 批量查询学校信息
        Map<Long, String> schoolMap = sSchoolService.batchQuerySchoolNames(schoolIds);

        // 批量查询点赞状态
        Map<Long, Boolean> likeStatusMap = Collections.emptyMap();
        String currentUserId = LoginContextHolder.getLoginId();
        if (currentUserId != null) {
            likeStatusMap = sPostLikeService.batchQueryLikeStatus(
                    postIds,
                    Long.valueOf(currentUserId),
                    PostLikeTypeEnums.LIKE.getType()
            );
        }

        for (SPostResponseVO vo : vos) {
            // 处理图片
            if (StringUtils.isNotBlank(vo.getImages())) {
                vo.setPostImages(JSONUtil.toList(vo.getImages(), String.class));
            }

            // 设置点赞状态
            vo.setIsLike(likeStatusMap.getOrDefault(vo.getId(), false));

            // 设置用户信息
            UserInfoDTO userInfo = userMap.get(vo.getUserId());
            if (userInfo != null) {
                vo.setUserNickName(userInfo.getNickName());
            }

            // 设置分类信息
            vo.setCategoryName(categoryMap.getOrDefault(vo.getCategoryId(), ""));

            // 设置学校信息
            vo.setSchoolName(schoolMap.getOrDefault(vo.getSchoolId(), ""));
        }

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(SPostRequestVO requestVO) {
        SPost existingPost = sPostService.queryById(requestVO.getId());
        if (existingPost == null || existingPost.getIsDeleted() == IsDeletedFlagEnum.DELETED.getVal()) {
            return false; // 帖子不存在或已删除
        }

        // 更新帖子基本信息
        SPost updatedPost = buildUpdatedPost(requestVO, existingPost);
        int updateCount = sPostService.update(updatedPost);

        // 处理标签更新
        if (updateCount > 0) {
            handlePostTags(requestVO, updatedPost.getId(), false);
        }

        return updateCount > 0;
    }

    private SPost buildUpdatedPost(SPostRequestVO requestVO, SPost existingPost) {
        // 创建更新后的实体
        SPost updatedPost = SPostConvert.INSTANCE.convert(requestVO);

        // 保留不应被覆盖的字段
        updatedPost.setUserId(existingPost.getUserId());

        // 处理图片更新
        if (CollectionUtil.isNotEmpty(requestVO.getPostImages())) {
            updatedPost.setImages(JSONUtil.toJsonStr(requestVO.getPostImages()));
        } else {
            // 如果没有提供新图片，保留原有图片
            updatedPost.setImages(existingPost.getImages());
        }

        // 确保关键字段不为空
        if (updatedPost.getViewCount() == null) updatedPost.setViewCount(existingPost.getViewCount());
        if (updatedPost.getLikeCount() == null) updatedPost.setLikeCount(existingPost.getLikeCount());
        if (updatedPost.getCommentCount() == null) updatedPost.setCommentCount(existingPost.getCommentCount());
        if (updatedPost.getIsDeleted() == null) updatedPost.setIsDeleted(existingPost.getIsDeleted());

        return updatedPost;
    }

    @Override
    public Boolean delete(Long id) {
        SPost entity = new SPost();
        entity.setId(id);
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return sPostService.update(entity) != 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(SPostRequestVO requestVO) {
        try {
            // 创建帖子
            SPost post = buildPostFromRequest(requestVO);
            sPostService.insert(post);

            // 处理标签关联
            handlePostTags(requestVO, post.getId(), true);

            return true;
        } catch (Exception e) {
            return false;
        }

    }

    private SPost buildPostFromRequest(SPostRequestVO requestVO) {
        SPost entity = SPostConvert.INSTANCE.convert(requestVO);
        Long userId = LoginContextHolder.getUserId();
        entity.setUserId(userId);
        entity.setPostStatus(CircleConstants.POST_STATUS_PUBLISHED);
        entity.setCommentCount(0);
        entity.setLikeCount(0);
        entity.setViewCount(0);

        // 校验图片和帖子内容合法性,脱敏处理,根据脱敏结果设置帖子状态
//        PostContentUtils.checkPostContent(requestVO);

        // 处理图片
        if (CollectionUtil.isNotEmpty(requestVO.getPostImages())) {
            entity.setImages(JSONUtil.toJsonStr(requestVO.getPostImages()));
        }

        return entity;
    }

    /**
     * 处理标签关联
     *
     * @param requestVO 请求参数
     * @param postId    帖子ID
     * @param isInsert  是否是插入操作
     */
    private void handlePostTags(SPostRequestVO requestVO, Long postId, boolean isInsert) {
        // 如果是更新操作，先删除旧的标签关联
        if (!isInsert) {
            sPostTagMappingService.deleteByPostId(postId);
        }

        List<String> tags = requestVO.getPostTagList();
        if (CollectionUtil.isEmpty(tags)) return;

        if (CollectionUtil.isEmpty(requestVO.getPostTagList())) return;

        // 获取或创建标签ID
        List<Long> tagIds = requestVO.getPostTagList().stream()
                .map(sPostTagService::getOrCreateTag)
                .collect(Collectors.toList());

        // 创建关联关系
        List<SPostTagMapping> mappings = tagIds.stream()
                .map(tagId ->
                        new SPostTagMapping(postId, tagId, requestVO.getSchoolId(), new Date(), IsDeletedFlagEnum.UN_DELETED.getVal())
                )
                .collect(Collectors.toList());

        sPostTagMappingService.batchInsert(mappings);
    }


    @Override
    public SPostResponseVO get(Long id) {
        SPost entity = sPostService.queryById(id);
        SPostResponseVO sPostResponseVO = SPostConvert.INSTANCE.convert(entity);
        // 将帖子图片字符串转换为数组
        if (ObjectUtil.isNotNull(sPostResponseVO.getImages())) {
            String images = sPostResponseVO.getImages();
            List<String> postImages = JSONUtil.toList(images, String.class);
            sPostResponseVO.setPostImages(postImages);
        }
        String userId = LoginContextHolder.getLoginId();
        // 用户是否点赞
        if (userId != null) {
            SPostLike sPostLike = new SPostLike();
            sPostLike.setLikeType(PostLikeTypeEnums.LIKE.getType());
            sPostLike.setPostId(id);
            sPostLike.setUserId(Long.valueOf(userId));
            sPostLike.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
            sPostResponseVO.setIsLike(sPostLikeService.queryByCondition(sPostLike) != null);
        }

        // 获取该帖子的话题
        SPostTagMapping queryEntity = new SPostTagMapping();
        queryEntity.setPostId(id);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        List<SPostTagMapping> sPostTagMappings = sPostTagMappingService.queryAllByCondition(queryEntity);
        if (CollectionUtil.isNotEmpty(sPostTagMappings)) {
            List<String> postTagList = sPostTagMappings.stream()
                    .map(sPostTagMapping -> {
                        SPostTag sPostTag = sPostTagService.queryById(sPostTagMapping.getTagId());
                        return sPostTag.getPostTagName();
                    })
                    .collect(Collectors.toList());
            sPostResponseVO.setPostTagList(postTagList);
        }

        UserInfoDTO userInfoDTO = userRPC.queryUserInfoByUid(sPostResponseVO.getUserId());
        if (ObjectUtil.isNotNull(userInfoDTO)) {
            sPostResponseVO.setUserNickName(userInfoDTO.getNickName());
            sPostResponseVO.setUserAvatar(userInfoDTO.getAvatar());
        }

        sPostResponseVO.setSchoolName(sSchoolService.queryById(sPostResponseVO.getSchoolId()).getSchoolName());

        sPostResponseVO.setCategoryName(sPostCategoryService.queryById(sPostResponseVO.getCategoryId()).getCategoryName());

        return sPostResponseVO;
    }

    @Override
    public Boolean view(Long postId) {
        int updateCount = sPostService.view(postId);
        return updateCount > 0;
    }

    @Override
    public List<TimeSlotPriceVO> getPinPricing() {
        // 获取当前时间
        Date now = new Date();

        // 生成时间段选项（示例：未来3天，每2小时一个时段）
        List<TimeSlotPriceVO> pricingList = new ArrayList<>();

        // 定义时段定价策略  TODO 根据数据分析动态配置
        Map<String, Double> priceStrategy = new HashMap<>();
        priceStrategy.put("golden", 10.0); // 黄金时段
        priceStrategy.put("normal", 5.0); // 普通时段
        priceStrategy.put("off", 2.0); // 低谷时段

        // 生成时间段选项（示例数据）
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);

        // 生成未来3天的时间段
        for (int day = 1; day <= 3; day++) {
            calendar.add(Calendar.DATE, 1);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);

            // 每天生成12个时段（每2小时）
            for (int hour = 0; hour < 24; hour += 2) {
                Date startTime = calendar.getTime();
                calendar.add(Calendar.HOUR, 2);
                Date endTime = calendar.getTime();

                // 确定时段类型 TODO 根据实际业务逻辑
                String slotType = determineSlotType(hour);

                // 创建VO
                TimeSlotPriceVO vo = new TimeSlotPriceVO();
                vo.setDate(new SimpleDateFormat("yyyy-MM-dd").format(startTime));
                vo.setStartTime(startTime);
                vo.setEndTime(endTime);
                vo.setPrice(priceStrategy.get(slotType));
                vo.setSlotType(slotType);

                pricingList.add(vo);
            }
        }

        return pricingList;
    }

    @Override
    public Boolean createPostPin(PostPinRequestVO request) {
        // 验证帖子是否存在且属于当前用户 - 当前不考虑这个逻辑，任何用户都可以置顶帖子

        // 验证时间有效性
        if (request.getEndTime().before(new Date()) ||
                request.getEndTime().before(request.getStartTime())) {
            throw exception(ErrorCodeConstants.CIRCLE_POST_PIN_TIME_INVALID);
        }

        // TODO 校验是否支付

        /**
         * 校验是否立即执行置顶
         * 是：置顶帖子
         * 否：构建redis缓存信息，等待定时任务扫描
         */
        if (request.getIsImmediately()) {
            SPost sPost = sPostService.queryById(request.getPostId());
            sPost.setIsPinned(IS_PINNED);
            sPost.setPinExpireTime(request.getEndTime());
            int updateCount = sPostService.update(sPost);
            return updateCount > 0;
        }

        buildPostPinTask(request);

        return true;
    }

    /**
     * 构建置顶任务
     *
     * @param request
     */
    private void buildPostPinTask(PostPinRequestVO request) {
        // 缓存相关信息入redis
        Map<String, Object> pinMap = new HashMap<>();
        pinMap.put("postId", request.getPostId());
        pinMap.put("startTime", request.getStartTime().getTime());
        pinMap.put("endTime", request.getEndTime().getTime());
        pinMap.put("pinOrderNo", request.getPinOrderNo());
        pinMap.put("createTime", System.currentTimeMillis());

        // 存储到Redis - 使用Hash结构
        String redisKey = redisUtil.buildKey(RedisCacheKey.POST_PIN.getCachePrefix(), request.getPostId().toString());
        redisUtil.putAllHash(redisKey, pinMap);

        // 设置过期时间（置顶结束后48小时自动清理）
        long expireSeconds = (request.getEndTime().getTime() - System.currentTimeMillis()) / 1000 + 172800;
        redisUtil.expire(redisKey, expireSeconds, TimeUnit.SECONDS);

        // 添加到延迟队列（用于定时任务扫描）
        addToPinQueue(request.getPostId(), request.getStartTime().getTime());
    }

    // 添加到延迟队列（使用ZSET）
    private void addToPinQueue(Long postId, long startTimestamp) {
        redisUtil.zAdd(RedisCacheKey.POST_PIN_QUEUE.getCachePrefix(), postId.toString(), startTimestamp);
    }

    @Override
    public String getPinOrderNo() {
        return pinOrderNoGenerator.genPinOrderNo();
    }


    /**
     * 时段类型判断逻辑 - 待优化
     *
     * @param hour
     * @return
     */
    private String determineSlotType(int hour) {
        if ((hour >= 7 && hour < 9) ||   // 早高峰
                (hour >= 11 && hour < 13) || // 午间
                (hour >= 17 && hour < 19) || // 晚高峰
                (hour >= 21 && hour < 23)) { // 夜间
            return "golden";
        } else if (hour >= 23 || hour < 6) { // 深夜
            return "off";
        } else {
            return "normal";
        }
    }


}
